package me.seu.demo.service.netty.handler.event;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import me.seu.demo.service.netty.handler.Process;
import me.seu.demo.service.netty.message.GpsMessage;
import me.seu.demo.service.netty.utils.ByteUtils;
import me.seu.demo.service.netty.utils.CommUtils;
import me.seu.demo.service.netty.utils.NetUtils;

/**
 * GPS单围栏、多围栏 报警包处理 0x26
 *
 * @author liangfeihu
 * @number 53669
 * @since 2021/4/7 下午5:22
 */
@Slf4j
public class AlertGps implements Process {

    @Override
    public void execute(GpsMessage msg) throws Exception {
        byte[] packetContent = msg.getPacketContent();
        // 处理年月日
        String dateTime = CommUtils.handleDateTime(packetContent);
        log.info("[AlertGps]dateTime={}", dateTime);
        // 处理卫星数、经纬度、速度
        handleLongitudeAndLatitude(packetContent);
        // 处理航行、状态
        String sail = handleSailState(packetContent);
        int lbsLength = 0xFF & packetContent[18];
        log.info("[AlertGps]sail={} lbsLength={}",  sail, lbsLength);
        // 处理MCC、MNC、LAC、Cell ID
        handleMccAndCell(packetContent);
        // todo 设备信息
        byte deviceInfo = packetContent[27];
        String deviceStr = getDeviceStatusInfo(deviceInfo);
        // 电压等级
        byte voltageLevel = packetContent[28];
        String voltageLevelDesc = CommUtils.getVoltageLevelDesc(voltageLevel);
        // GSM信号等级
        byte gsmLevel = packetContent[29];
        String gsmSignalLevelDesc = CommUtils.getGsmSignalLevelDesc(gsmLevel);
        log.info("[AlertGps]deviceInfo=0x{} voltageLevel={} gsmSignalLevel={}",
                deviceStr, voltageLevelDesc, gsmSignalLevelDesc);
        // 报警语言详解
        byte alert = packetContent[30];
        String alertDesc = CommUtils.getAlertDesc(alert);
        byte language = packetContent[31];
        String languageDesc = CommUtils.getLanguageDesc(language);
        log.info("[AlertGps] alert={} language={}", alertDesc, languageDesc);
        if (0x27 == msg.getProtocolNo()) {
            // 多围栏
            int num = 0xFF & packetContent[32];
            log.info("[AlertGps] 多围栏 num={} ", num);
        }

        // 返回响应包
        sedGpsReplyMsg(msg);
    }

    private String getDeviceStatusInfo(byte deviceInfo) {
        StringBuilder builder = new StringBuilder();
        int one = 0x00000001 & (deviceInfo >> 7);
        builder.append(one == 0 ? "油电接通" : "油电断开").append("、");
        int two = 0x00000001 & (deviceInfo >> 6);
        builder.append(two == 1 ? "GPS 已定位" : "GPS 未定位").append("、");

        byte alert = (byte) (0x00000007 & (deviceInfo >> 3));
        builder.append(getAlertDesc(alert)).append("、");

        int three = 0x00000001 & (deviceInfo >> 2);
        builder.append(three == 1 ? "已接电源充电" : "未接电源充电").append("、");
        int four = 0x00000001 & (deviceInfo >> 1);
        builder.append(four == 1 ? "ACC 高" : "ACC 低").append("、");
        int five = 0x00000001 & deviceInfo;
        builder.append(five == 1 ? "设防" : "撤防");
        return builder.toString();
    }

    public static String getAlertDesc(byte alert) {
        if (0x00 == alert) {
            return "正常未报警";
        } else if (0x01 == alert) {
            return "震动报警";
        } else if (0x02 == alert) {
            return "断电报警";
        } else if (0x03 == alert) {
            return "低电报警";
        } else if (0x04 == alert) {
            return "SOS求救";
        } else if (0x05 == alert) {
            return "超时报警（疲劳驾驶）";
        } else if (0x06 == alert) {
            return "超速报警";
        }
        return "未知";
    }

    private void sedGpsReplyMsg(GpsMessage msg) {
        // 构造GPS报警响应包
        msg.setProtocolNo((byte)0x26);
        byte[] replyPacket = NetUtils.buildCommonReplyPacket(msg);

        ChannelHandlerContext ctx = msg.getCtx();
        if (ctx.channel().isWritable()) {
            // 将GPS报警响应包发送出去
            ctx.pipeline().writeAndFlush(Unpooled.wrappedBuffer(replyPacket));
        } else {
            ctx.pipeline().close();
        }
    }

    private void handleMccAndCell(byte[] packetContent) {
        byte[] mcc = new byte[]{packetContent[19], packetContent[20]};
        int mccNum = ByteUtils.byteArrayToInt(mcc, true);
        int mncNum = 0xFF & packetContent[21];
        byte[] lac = new byte[]{packetContent[22], packetContent[23]};
        int lacNum = ByteUtils.byteArrayToInt(lac, true);
        byte[] cell = new byte[]{0x00, packetContent[24], packetContent[25], packetContent[26]};
        int cellId = ByteUtils.byteArrayToInt(cell);
        log.info("[AlertGps]mccNum:{} mncNum:{} lacNum:{} cellId:{}", mccNum, mncNum, lacNum, cellId);
    }

    private String handleSailState(byte[] packetContent) {
        byte[] sail = new byte[]{packetContent[16], packetContent[17]};
        StringBuilder builder = new StringBuilder();
        int one = 0x00000001 & (sail[0] >> 4);
        builder.append(one == 1 ? "GPS 已定位" : "GPS 未定位").append(", ");
        int two = 0x00000001 & (sail[0] >> 5);
        builder.append(two == 0 ? "实时GPS" : "差分定位").append("、");
        int three = 0x00000001 & (sail[0] >> 2);
        builder.append(three == 1 ? "北纬" : "南纬").append("、");
        int four = 0x00000001 & (sail[0] >> 3);
        builder.append(four == 1 ? "西经" : "东经").append("、");

        byte[] intArr = new byte[4];
        intArr[0] = 0x00;
        intArr[1] = 0x00;
        intArr[2] = (byte) (0x03 & sail[0]);
        intArr[3] = sail[1];
        int sailState = ByteUtils.byteArrayToInt(intArr);
        builder.append("航向").append(sailState).append("° 。");
        return builder.toString();
    }

    private void handleLongitudeAndLatitude(byte[] packetContent) {
        int gpsNum = 0x0F & packetContent[6];
        int gpsLength = 0x0F & (packetContent[6] >> 4);
        //longitude and latitude
        byte[] lat = new byte[]{packetContent[7], packetContent[8], packetContent[9], packetContent[10]};
        double latitude = ByteUtils.byteArrayToInt(lat) / 1800000d;
        byte[] lon = new byte[]{packetContent[11], packetContent[12], packetContent[13], packetContent[14]};
        double longitude = ByteUtils.byteArrayToInt(lon) / 1800000d;
        int speed = 0xFF & packetContent[15];
        log.info("[AlertGps]gpsNum:{} gpsLength:{} longitude:{} latitude:{} speed:{}",
                gpsNum, gpsLength, longitude, latitude, speed);
    }

}
